﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using MDK;
using MDK.Physics;
using ZedGraph;

namespace InvisibleCollapse
{
    public class InvisibleCollapse : GraphicPrimitive
    {
        #region Кухня моделирования

        // частицы
        Particle Initial = new Particle();
        MovingParticle First;
        MovingParticle Second;

        // углы отлёта
        double a;

        // для рисования траектории
        Point fPrev;
        Point sPrev;
        #endregion


        #region Конструкторы
        public InvisibleCollapse()
            : base(0, 0, new Size())
        {
            AddParametersToTemplate();
            this.Needs = ExperimentNeeds.Normal; // нужды
        }

        public InvisibleCollapse(int Left, int Top, Size Size)
            : base(Left, Top, Size)
        {
            this.Needs = ExperimentNeeds.Normal; // нужды

            // передаём размеры
            this.Left = Left;
            this.Top = Top;

            this.Size = Size;

            //создаём список по умолчанию
            AddParametersToTemplate();
        }
        #endregion

        #region Методы взаимодействия с главным модулем
        public override ExperimentAbout GetAbout()
        {
            return new ExperimentAbout("InvisibleCollapse", "Моделирование распада нейтральной частицы", "Моделирование распада нейтральной(невидимой для детектеров) частицы.\n На практике видны только следы частиц, получившихся от распада.\n Распад происходит в магнитном поле, из-за которого продукты распада летят в разные стороны, что позволяет определять их заряд.\n");
        }
        private void AddParametersToTemplate()
        {
            ParameterListTemplate = new ParameterList();

            ParameterListTemplate.Add("Энергия первой частицы", "E1", 50);
            ParameterListTemplate.Add("Импульс первой частицы", "P1", 20);
            

            ParameterListTemplate.Add("Энергия второй частицы", "E2", 100);
            ParameterListTemplate.Add("Импульс второй частицы", "P2", 40);

            ParameterListTemplate.Add("Угол отлёта частиц(rad)", "a", 0);
            ParameterListTemplate.Add("Модуль заряда частиц", "Q", 3);
            ParameterListTemplate.Add("Вектор электромагнитной индукции", "B", 1);
        }

        public override void SetParameters(ParameterList pList)
        {
            a = pList["a"];

            First  = new MovingParticle(Math.PI + pList["a"], pList["Q"], pList["E1"], pList["P1"], pList["B"]);
            Second = new MovingParticle(Math.PI - pList["a"], -pList["Q"], pList["E2"], pList["P2"], pList["B"]);
        }


        public override ParameterList GetParameters()
        {
            ParameterList RetList = new ParameterList();

            RetList.Add("Энергия первой частицы", "E1", First.Energy);
            RetList.Add("Импульс первой частицы", "P1", First.p);
           
             RetList.Add("Энергия второй частицы", "E2", Second.Energy);
            RetList.Add("Импульс второй частицы", "P2", Second.p);
            
            RetList.Add("Угол разлёта частиц(rad)", "a", a);
            RetList.Add("Модуль заряда частиц", "Q", First.Q);

            RetList.Add("Вектор электромагнитной индукции", "B", First.B);

            return RetList;
        }

        public override PointPairList GetResults()
        {
            // todo: возвращаем результаты для статистики
            return new PointPairList();
        }
        #endregion


        /// <summary>
        /// Метод рисования
        /// </summary>
        /// <param name="e"></param>
        public override void Draw(System.Windows.Forms.PaintEventArgs e)
        {
            // считаем массы и скорости
            CountParticleParameters();

            //MessageBox.Show("Масса невидимой частицы: " + Initial.m);

            // задаём точку разлёта частиц
            First.x = this.Size.Width / 2;
            First.y = this.Size.Height / 2;

            Second.x = First.x;
            Second.y = First.y;

            //точки
            fPrev = new Point((int)First.x, (int)First.y);
            sPrev = new Point((int)Second.x, (int)Second.y);

            Pen neutral = new Pen(Brushes.Black, 4f);
            neutral.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

            e.Graphics.DrawLine(neutral, this.Size.Width / 2, this.Size.Height * 4/5, this.Size.Width / 2, this.Size.Height / 2);

            //двигаемся 700 раз в магнитном поле
            try
            {

                Pen rPen = new Pen(Brushes.Red, 4f);
                Pen bPen = new Pen(Brushes.Blue, 4f);

                for (int i = 0; i < 700; i++)
                {
                    First.Move();
                    Second.Move();

                    
                    e.Graphics.DrawLine(rPen, fPrev, new Point((int)First.x, (int)First.y));
                    e.Graphics.DrawLine(bPen, sPrev, new Point((int)Second.x, (int)Second.y));

                    fPrev = new Point((int)First.x, (int)First.y);
                    sPrev = new Point((int)Second.x, (int)Second.y);
                }
            }
            catch (Exception ex)
            {
            }

            LegendDrawer d = new LegendDrawer(0,0,  "Масса частицы: " + Initial.m);

            d.AddTrajectory(Color.Black, "Траектория невидимой частицы до распада");
            d.AddTrajectory(Color.Red, "Траектория частицы с положительным зарядом");
            d.AddTrajectory(Color.Blue, "Траектория частицы с отрицательным зарядом");

            d.Draw(e.Graphics);
        }

        private void CountParticleParameters()
        {
            
            // инварантная масса первичной частицы
            Initial = new Particle();
            Particle[] Collapsed = { First, Second };
            Initial.CollapsedFrom(Collapsed);


            First.angle = (Math.PI - a)/2 - Math.PI/2;
            Second.angle = Math.PI - (Math.PI - a) / 2 - Math.PI / 2;

            First.ReCount();
            Second.ReCount();
            
        }        
    }
}
